import { createStore, Commit } from 'vuex'
import axios, { AxiosRequestConfig } from 'axios'
import { arrToObj, objToArr } from './helper'
export interface ResponseType<P = {}> {
  code: number;
  msg: string;
  data: P;
}
export interface UserProps {
  isLogin: boolean;
  nickName?: string;
  _id?: string;
  column?: string;
  email?: string;
  avatar?: ImageProps;
  description?: string;
}
export interface ImageProps {
  _id?: string;
  url?: string;
  createdAt?: string;
  fitUrl?: string;
}
export interface ColumnProps {
  _id: string;
  title: string;
  avatar?: ImageProps;
  description: string;
}
export interface PostProps {
  _id?: string;
  title: string;
  excerpt?: string;
  content?: string;
  // 因为现在传的是一个id 是个简单的 string 不是 ImageProps，所以是 string也可以
  image?: ImageProps | string;
  createdAt?: string;
  column: string;
  author?: string | UserProps;
  isHTML?: boolean;
}
// 转换类型，将 ColumnProps[] 和 PostProps[] 转换为对象类型
interface ListProps<P> {
  [id: string]: P;
}

export interface GlobalErrorProps {
  status: boolean;
  message?: string;
}
export interface GlobalDataProps {
  error: GlobalErrorProps;
  token: string;
  loading: boolean;
  // 增加一个 total 属性来表示加载出来的 column 个数
  columns: { data: ListProps<ColumnProps>; currentPage: number; total: number };
  posts: { data: ListProps<PostProps>; loadedColumns: string[] };
  user: UserProps;
}
// const asyncAndCommit = async (url: string, mutationName: string, commit: Commit) => {
//   const { data } = await axios.get(url)
//   commit(mutationName, data)
//   return data
// }
// const asyncAndCommit = async (url: string, mutationName: string, commit: Commit, payload: any) => {
//   const { data } = await axios.post(url, payload)
//   commit(mutationName, data)
//   return data
// }
// 重构代码
const asyncAndCommit = async(url: string, mutationName: string, commit: Commit, config: AxiosRequestConfig = { method: 'get' }, extraData?: unknown) => {
  const { data } = await axios(url, config)
  // 为了适应 fetchPosts 的需求
  if (extraData) {
    commit(mutationName, { data, extraData })
  } else {
    commit(mutationName, data)
  }
  return data
}

const store = createStore<GlobalDataProps>({
  state: {
    error: { status: false },
    // 不存在则设置为空
    token: localStorage.getItem('token') || '',
    loading: false,
    // 增加一个 total 属性来表示加载出来的 column 个数，设置其初始值为 0
    columns: { data: {}, currentPage: 0, total: 0 },
    posts: { data: {}, loadedColumns: [] },
    user: { isLogin: false }
  },
  mutations: {
    // 测试用的 login
    // login(state) {
    //   state.user = { ...state.user, isLogin: true, name: 'demonlb' }
    // },
    createPost(state, newPost) {
      state.posts.data[newPost._id] = newPost
    },
    // 添加删除逻辑
    deletePost(state, { data }) {
      delete state.posts.data[data._id]
    },
    fetchColumns(state, rawData) {
      const { data } = state.columns
      const { list, count, currentPage } = rawData.data
      state.columns = {
        data: { ...data, ...arrToObj(list) },
        total: count,
        // 因为 currentPage 有可能是一个 string 类型，所以给它乘以1
        currentPage: currentPage * 1
      }
    },
    fetchColumn(state, rawData) {
      state.columns.data[rawData.data._id] = rawData.data
    },
    fetchPosts(state, { data: rawData, extraData: columnId }) {
      // 需要给数组多添加一项 cid
      // 需要知道请求的 columnid
      state.posts.data = { ...state.posts.data, ...arrToObj(rawData.data.list) }
      state.posts.loadedColumns.push(columnId)
    },
    fetchPost(state, rawData) {
      state.posts.data[rawData.data._id] = rawData.data
    },
    updatePost(state, { data }) {
      state.posts.data[data._id] = data
    },
    setLoading(state, status) {
      state.loading = status
    },
    setError(state, error: GlobalErrorProps) {
      state.error = error
    },
    login(state, rawData) {
      const { token } = rawData.data
      state.token = token
      localStorage.setItem('token', token)
      // 设置 token
      axios.defaults.headers.common.Authorization = `Bearer ${token}`
    },
    fetchCurrentUser(state, rawData) {
      state.user = { isLogin: true, ...rawData.data }
    },
    logout(state) {
      // 将token置空
      state.token = ''
      // 将 user 的状态置为 未登录状态
      state.user = { isLogin: false }
      // 清除登录的 token
      localStorage.removeItem('token')
      // 最后将证书删除
      delete axios.defaults.headers.common.Authorization
    }
  },
  actions: {
    // 原来
    // fetchColumns(context) {
    //   axios.get('/columns').then(response => {
    //     context.commit('fetchColumns', response.data)
    //   })
    // },
    // 修改1
    // async fetchColumns({ commit }) {
    //   const { data } = await axios.get('/columns')
    //   commit('fetchColumns', data)
    // },
    // 修改2
    fetchColumns({ state, commit }, params = {}) {
      // 从页面中发送的请求中拿到 currentPage 和 pageSize，如果没有则设置为 1 和 6
      const { currentPage = 1, pageSize = 6 } = params
      // 如果现在的 page 小于 currentPage时，才请求
      if (state.columns.currentPage < currentPage) {
        return asyncAndCommit(`/columns?currentPage=${currentPage}&pageSize=${pageSize}`, 'fetchColumns', commit)
      }
    },
    fetchColumn({ state, commit }, cid) {
      // 如果是有 cid 才发请求，没有则不发送请求
      if (!state.columns.data[cid]) {
        return asyncAndCommit(`/columns/${cid}`, 'fetchColumn', commit)
      }
    },
    fetchPosts({ state, commit }, cid) {
      if (!state.posts.loadedColumns.includes(cid)) {
        return asyncAndCommit(`/columns/${cid}/posts`, 'fetchPosts', commit, { method: 'get' }, cid)
      }
    },
    // 拿到每个专栏里的内容
    fetchPost({ state, commit }, id) {
      // 如果返回的数据中有 content 证明需要重新发送
      const currentPost = state.posts.data[id]
      // 如果没取过且在列表中没拿 content（拿的位置不对）
      if (!currentPost.content) {
        return asyncAndCommit(`/posts/${id}`, 'fetchPost', commit)
      } else {
        return Promise.resolve({ data: currentPost })
      }
    },
    fetchCurrentUser({ commit }) {
      return asyncAndCommit('/user/current', 'fetchCurrentUser', commit)
    },
    createPost({ commit }, payload) {
      return asyncAndCommit('/posts', 'createPost', commit, { method: 'post', data: payload })
    },
    // 添加删除逻辑
    deletePost({ commit }, id) {
      return asyncAndCommit(`/posts/${id}`, 'deletePost', commit, { method: 'delete' })
    },
    login({ commit }, payload) {
      return asyncAndCommit('/user/login', 'login', commit, { method: 'post', data: payload })
    },
    // 组合action
    // 拿到dispatch 和 loginData 的登录数据
    loginAndFetch({ dispatch }, loginData) {
      return dispatch('login', loginData).then(() => {
        return dispatch('fetchCurrentUser')
      })
    },
    // 发送 PATCH 请求来更新文章内容
    updatePost({ commit }, { id, payload }) {
      return asyncAndCommit(`/posts/${id}`, 'updatePost', commit, {
        method: 'patch',
        data: payload
      })
    }
  },
  getters: {
    getColumnById: (state) => (id: string) => {
      return state.columns.data[id]
    },
    getPostByCid: (state) => (cid: string) => {
      return objToArr(state.posts.data).filter(post => post.column === cid)
    },
    getCurrentPost: (state) => (id: string) => {
      return state.posts.data[id]
    },
    getColumns: (state) => {
      return objToArr(state.columns.data)
    }
  }
})

export default store
